/* tslint:disable:no-redundant-jsdoc */
import {Injectable} from '@angular/core';
import {
    HttpClient, HttpErrorResponse,
    HttpEvent,
    HttpHandler,
    HttpHeaders,
    HttpInterceptor,
    HttpParams,
    HttpRequest,
    HttpResponse
} from '@angular/common/http';
import {Observable, of} from 'rxjs';
import {catchError, mergeMap} from 'rxjs/operators';
import Utils from '@const/Utils';

@Injectable({
    providedIn: 'root'
})
export class HttpService implements HttpInterceptor {

    constructor(private http: HttpClient) {
    }

    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        // 统一加上服务端前缀
        let url = req.url;
        if (!url.startsWith('https://') && !url.startsWith('http://')) {
            url = `http://jlapp.qchfy.com/api` + url;
        }

        const newReq = req.clone({
            url,
        });
        return next.handle(newReq).pipe(
            mergeMap((event: any) => {
                // 允许统一对请求错误处理，这是因为一个请求若是业务上错误的情况下其HTTP请求的状态是200的情况下需要
                if (event instanceof HttpResponse && event.status === 200) {
                    return this.handleData(event);
                }
                // 若一切都正常，则后续操作
                return of(event);
            }),
            catchError((err: HttpErrorResponse) => this.handleData(err)),
        );
    }

    private handleData(event: HttpResponse<any> | HttpErrorResponse): Observable<any> {
        // 业务处理：一些通用操作
        switch (event.status) {
            case 200:
            case 400: // Bad Request
            case 401: // 未登录状态码
            case 403:
            case 404:
            case 500:
            default:
                if (event instanceof HttpErrorResponse) {
                    console.warn(
                        '未可知错误，大部分是由于后端不支持CORS或无效配置引起',
                        event,
                    );
                }
                break;
        }
        return of(event);
    }

    /**
     * 统一请求入口
     * @param method
     * @param url
     * @param body
     * @param options
     */
    request(method, url, body, options = {}) {
        body = body || {};

        let userInfo = Utils.getUserInfo();
        let SessionID = localStorage.getItem('SessionID');

        body.SessionID = SessionID;

        if (body.data) {
            Object.assign(body.data, userInfo);
        }

        let keys = Object.keys(body);
        for (let key of keys) {
            if (body[key] instanceof Object) {
                body[key] = JSON.stringify(body[key]);
            }
        }

        let defaultOptions = {
            headers: new HttpHeaders({'Content-Type': 'application/x-www-form-urlencoded'}),
            responseType: 'json',
            observe: 'body',
            body: null,
            params: null
        };

        Object.assign(defaultOptions, options);

        if (method === 'post') {
            defaultOptions.body = new HttpParams({fromObject: body});
        } else {
            defaultOptions.params = body;
        }

        // @ts-ignore
        return this.http.request(method, url, defaultOptions).toPromise();
    }

    /**
     * 简单post封装
     * @param url
     * @param body
     */
    post(url, body): Promise<any> {
        return this.request('post', url, body);
    }

    /**
     * 简单get封装
     * @param url
     * @param body
     */
    get(url, body): Promise<any> {
        return this.request('get', url, body);
    }

    /**
     * 调用queryApi.do
     * @param queryBean
     * @param body
     */
    query(queryBean, body) {
        return this.post('', body);
    }

    api(interfaceId, params = {}) {
        let requestParams = {interfaceId: interfaceId, data: params || {}};
        return this.post('/Inbound/invoke.do', requestParams);
    }
}
